package models

import (
	"time"

	"github.com/google/uuid"
	"gorm.io/gorm"
)

// User represents a user in the system
type User struct {
	ID           string `gorm:"primaryKey" json:"id"`
	Username     string `gorm:"uniqueIndex;not null;size:50" json:"username"`
	Email        string `gorm:"uniqueIndex;not null;size:100" json:"email"`
	PasswordHash string `gorm:"not null;size:255" json:"-"`
	FullName     string `gorm:"size:100" json:"full_name"`
	IsAdmin      bool   `gorm:"default:false" json:"is_admin"`
	IsActive     bool   `gorm:"default:true" json:"is_active"`
	CreatedAt    time.Time `json:"created_at"`
	UpdatedAt    time.Time `json:"updated_at"`
}

// Repository represents a repository in the system
type Repository struct {
	ID             string `gorm:"primaryKey" json:"id"`
	Name           string `gorm:"not null;size:255" json:"name"`
	Namespace      string `gorm:"not null;size:100" json:"namespace"`
	Description    string `gorm:"type:text" json:"description"`
	IsPublic       bool   `gorm:"default:false" json:"is_public"`
	RepositoryType string `gorm:"not null;size:50" json:"repository_type"`
	OwnerID        string `gorm:"not null" json:"owner_id"`
	CreatedAt      time.Time `json:"created_at"`
	UpdatedAt      time.Time `json:"updated_at"`
}

// Manifest represents a Docker manifest
type Manifest struct {
	ID           string `gorm:"primaryKey" json:"id"`
	RepositoryID string `gorm:"not null" json:"repository_id"`
	Digest       string `gorm:"not null;size:255;uniqueIndex" json:"digest"`
	MediaType    string `gorm:"not null;size:100" json:"media_type"`
	Content      []byte `gorm:"type:blob;not null" json:"-"`
	SizeBytes    int64  `gorm:"not null" json:"size_bytes"`
	CreatedAt    time.Time `json:"created_at"`
	UpdatedAt    time.Time `json:"updated_at"`
}

// Blob represents a Docker blob
type Blob struct {
	ID          string `gorm:"primaryKey" json:"id"`
	Digest      string `gorm:"not null;size:255;uniqueIndex" json:"digest"`
	MediaType   string `gorm:"size:100" json:"media_type"`
	SizeBytes   int64  `gorm:"not null" json:"size_bytes"`
	StoragePath string `gorm:"not null;size:500" json:"storage_path"`
	CreatedAt   time.Time `json:"created_at"`
}

// Upload represents an upload session
type Upload struct {
	ID           string     `gorm:"primaryKey" json:"id"`
	UUID         string     `gorm:"not null;size:255;uniqueIndex" json:"uuid"`
	RepositoryID string     `gorm:"not null" json:"repository_id"`
	BlobDigest   *string    `gorm:"size:255" json:"blob_digest"`
	SizeBytes    int64      `gorm:"default:0" json:"size_bytes"`
	StoragePath  string     `gorm:"not null;size:500" json:"storage_path"`
	Status       string     `gorm:"not null;size:20;default:'active'" json:"status"`
	StartedAt    time.Time  `json:"started_at"`
	CompletedAt  *time.Time `json:"completed_at"`
	ExpiresAt    time.Time  `json:"expires_at"`
}

// Tag represents a repository tag
type Tag struct {
	ID             string  `gorm:"primaryKey" json:"id"`
	RepositoryID   string  `gorm:"not null" json:"repository_id"`
	Name           string  `gorm:"not null;size:255" json:"name"`
	ManifestDigest *string `gorm:"size:255" json:"manifest_digest"`
	CreatedAt      time.Time `json:"created_at"`
	UpdatedAt      time.Time `json:"updated_at"`
}

// Artifact represents a software artifact (jar, war, tar, etc.)
type Artifact struct {
	ID           string `gorm:"primaryKey" json:"id"`
	Name         string `gorm:"not null;size:255" json:"name"`
	Version      string `gorm:"not null;size:100" json:"version"`
	Type         string `gorm:"not null;size:20" json:"type"`
	Size         int64  `gorm:"not null" json:"size"`
	Checksum     string `gorm:"not null;size:255" json:"checksum"`
	MimeType     string `gorm:"not null;size:100" json:"mime_type"`
	StoragePath  string `gorm:"not null;size:500" json:"storage_path"`
	RepositoryID string `gorm:"not null" json:"repository_id"`
	UploadedBy   string `gorm:"not null;size:100" json:"uploaded_by"`
	Description  string `gorm:"type:text" json:"description"`
	Downloads    int64  `gorm:"default:0" json:"downloads"`
	CreatedAt    time.Time `json:"created_at"`
	UpdatedAt    time.Time `json:"updated_at"`
}

// BeforeCreate hooks to generate UUIDs
func (u *User) BeforeCreate(tx *gorm.DB) error {
	if u.ID == "" {
		u.ID = uuid.New().String()
	}
	return nil
}

func (r *Repository) BeforeCreate(tx *gorm.DB) error {
	if r.ID == "" {
		r.ID = uuid.New().String()
	}
	return nil
}

func (m *Manifest) BeforeCreate(tx *gorm.DB) error {
	if m.ID == "" {
		m.ID = uuid.New().String()
	}
	return nil
}

func (b *Blob) BeforeCreate(tx *gorm.DB) error {
	if b.ID == "" {
		b.ID = uuid.New().String()
	}
	return nil
}

func (u *Upload) BeforeCreate(tx *gorm.DB) error {
	if u.ID == "" {
		u.ID = uuid.New().String()
	}
	return nil
}

func (t *Tag) BeforeCreate(tx *gorm.DB) error {
	if t.ID == "" {
		t.ID = uuid.New().String()
	}
	return nil
}

func (a *Artifact) BeforeCreate(tx *gorm.DB) error {
	if a.ID == "" {
		a.ID = uuid.New().String()
	}
	return nil
}